package com.cfs.config;

import com.cfs.config.cache.ShiroRedisCacheManager;
import com.cfs.config.filter.CustomAccessControlFilter;
import com.cfs.config.filter.CustomFormAuthenticationFilter;
import com.cfs.custom.MyRelam;

import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Created by Administrator on 2017/9/26/026.
 */
@SuppressWarnings("ALL")
@Configuration
public class ShiroConfig {

    @Bean
    public MyRelam getMyRelam(){
        MyRelam myRelam = new MyRelam();
        myRelam.setCacheManager(cacheManager());
        myRelam.setCachingEnabled(true);
        myRelam.setAuthorizationCachingEnabled(true);
        myRelam.setAuthenticationCachingEnabled(false);
        return myRelam;
    }

    @Bean
    public SessionDAO sessionDAO(){
        return new SessionDAO();
    }


    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }

    /**
     * 启用shrio授权注解拦截方式，AOP式方法级权限检查
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
        daap.setProxyTargetClass(true);
        return daap;
    }


    /**
     * 安全管理器
     */
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setSessionManager(defaultWebSessionManager());
        securityManager.setRealm(getMyRelam());
        securityManager.setRememberMeManager(rememberMeManager());
        return securityManager;
    }


    /**
     * session管理器
     */
    @Bean
    public DefaultWebSessionManager defaultWebSessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionDAO(sessionDAO());
        sessionManager.setDeleteInvalidSessions(false);
        sessionManager.setSessionValidationSchedulerEnabled(true);
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        sessionManager.setSessionIdCookie(simpleCookieId());
        return sessionManager;
    }

    @Bean
    public SimpleCookie simpleCookieId(){
        SimpleCookie simpleCookie = new SimpleCookie();
        simpleCookie.setName("M-SESSION-ID");
        simpleCookie.setDomain("localhost");
        simpleCookie.setPath("/");
        simpleCookie.setHttpOnly(false);
        simpleCookie.setMaxAge(1800000);
        return simpleCookie;
    }

    /**
     * Cookie
     * @return
     */
    @Bean
    public CookieRememberMeManager rememberMeManager() {
        CookieRememberMeManager manager = new CookieRememberMeManager();
        manager.setCipherKey(Base64.decode("Z3VucwAAAAAAAAAAAAAAAA=="));
        manager.setCookie(rememberMeCookie());
        return manager;
    }


    /**
     * 记住密码Cookie
     */
    @Bean
    public SimpleCookie rememberMeCookie() {
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        simpleCookie.setHttpOnly(true);
        simpleCookie.setMaxAge(7 * 24 * 60 * 60);//7天
        return simpleCookie;
    }


    /**
     * 在方法中 注入 securityManager,进行代理控制
     */
    @Bean
    public MethodInvokingFactoryBean methodInvokingFactoryBean(DefaultWebSecurityManager securityManager) {
        MethodInvokingFactoryBean bean = new MethodInvokingFactoryBean();
        bean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager");
        bean.setArguments(new Object[]{securityManager});
        return bean;
    }


    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor =
                new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }


    @Bean
    public JavaUuidSessionIdGenerator javaUuidSessionIdGenerator(){
        return new JavaUuidSessionIdGenerator();
    }

    @Bean
    public CustomFormAuthenticationFilter customFormAuthenticationFilter(){
        return new CustomFormAuthenticationFilter();
    }

    /**
     * @Description: 自定义过滤器
     * @Author:[yuxuan]
     * @Date:[2017年9月28日 下午8:25:46]  
     * @throws  
     */
    public CustomAccessControlFilter customAccessControlFilter(){
        return new CustomAccessControlFilter();
    }

    @Bean
    public CacheManager cacheManager() {
    	ShiroRedisCacheManager redisCacheManager = new ShiroRedisCacheManager();
    	return redisCacheManager;
    }
    
    /**
     * Shiro的过滤器链
     */
    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);

        Map<String, Filter> filterMap = new LinkedHashMap<>();
        filterMap.put("access", customAccessControlFilter());
        shiroFilter.setFilters(filterMap);
        /**
         * 默认的登陆访问url
         */
        shiroFilter.setLoginUrl("/login");
        /**
         * 登陆成功后跳转的url
         */
        shiroFilter.setSuccessUrl("/index");
        /**
         * 没有权限跳转的url
         */
        shiroFilter.setUnauthorizedUrl("/global/error");
        /**
         * 配置shiro拦截器链
         *
         * anon  不需要认证
         * authc 需要认证
         * user  验证通过或RememberMe登录的都可以
         *
         */

        Map<String, String> hashMap = new LinkedHashMap<>();
        hashMap.put("/resources/**", "anon");
        hashMap.put("/swagger*/**","anon");
        hashMap.put("/logins", "anon");
        hashMap.put("/**", "authc");
        shiroFilter.setFilterChainDefinitionMap(hashMap);
        return shiroFilter;
    }

}
